package com.ryan.controller;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import com.ryan.entity.Products;
import com.ryan.service.ProductFeign;
import jdk.nashorn.internal.objects.annotations.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.List;

/**
 * @author raofy
 * @date 2021-09-23 13:43
 * @desc 调用商品微服务对应的URL
 */
@Slf4j
@RestController
@RequestMapping("page")
public class PageController {

    @Autowired
    RestTemplate restTemplate;

    @Autowired
    private DiscoveryClient discoveryClient;

    @Autowired
    private ProductFeign productFeign;

    @GetMapping("getDate/{id}")
    public Products findDataById(@PathVariable Integer id) {
        // 使用RestTemplate进行访问请求
//        Products object = restTemplate.getForObject("http://localhost:9000/product/query/" + id, Products.class);
//        log.info("从product获得对象{}", object);
//        return object;

        // 使用Feign进行访问请求
        return productFeign.query(id);
    }

    @GetMapping("getProduct/{id}")
    public Products findProductById(@PathVariable Integer id) {
        // 获取eureka中已经注册的product实例集合
        List<ServiceInstance> instances = discoveryClient.getInstances("product");
        // 获取集合中的第一个
        ServiceInstance instanceInfo = instances.get(0);
        // 将实例信息拼接IP地址信息
        String hostName = instanceInfo.getHost();
        int port = instanceInfo.getPort();
        String url = "http://" + hostName + ":" + port + "/product/query/" + id;
        // 调用
        Products object = restTemplate.getForObject(url, Products.class);
        log.info("从product获得对象{}", object);
        return object;
    }

    @GetMapping("loadBalance")
    public String findBalancesPort() {
        // 使用RestTemplate进行访问请求
//        String url = "http://product/server/port";
//        String portString = restTemplate.getForObject(url, String.class);
//        log.info("从product获得对象{}", portString);
//        return portString;


        // 使用Feign进行访问请求
        return productFeign.findServerPort();
    }

    /**
     * 定义服务降级处理
     */
    @HystrixCommand(
            threadPoolKey = "getProductServerPort2",
            threadPoolProperties = {
                    @HystrixProperty(
                            name = "coreSize",
                            value = "1"), // 线程数
                    @HystrixProperty(name = "maxQueueSize",
                            value = "20") // 等待队列长 度
            },
            // commandProperties熔断的一些细节属性配置
            commandProperties = {
                    // 每一个属性都是一个HystrixProperty
                    @HystrixProperty(
                            name = "execution.isolation.thread.timeoutInMilliseconds",
                            value = "2000"),
                    @HystrixProperty(
                            name = "",
                            value = ""
                    )
            },
            // 定义回退方法
            fallbackMethod = "myFallBack"
    )


    @RequestMapping("/getPort2")
    public String getProductServerPort2() {
        String url = "http://product/server/port";
        return restTemplate.getForObject(url, String.class);
    }

    /**
     * 定义回退方法，返回兜底数据
     *
     * @return
     */
    public String myFallBack() {
        return "-1";
    }


    /**
     *  8秒钟内，请求次数达到2个，并且失败率在50%以上，就跳闸 * 跳闸后活动窗口设置为3s
     */
    @HystrixCommand(commandProperties = {
            //统计窗口时间的设置
            @HystrixProperty(name = "metrics.rollingStats.timeInMilliseconds",value = "8000"),
            //统计窗口内的最小请求数
            @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value = "2"),
            //统计窗口内错误请求阈值的设置 50%
            @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value = "50"),
            //自我修复的活动窗口时间
            @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds",value = "3000") } )
    @RequestMapping("/getPort3")
    public String getProductServerPort3() {
        String url = "http://product/server/port";
        return restTemplate.getForObject(url, String.class);
    }

}

